//
// Created by hkkzzxz on 24-8-31.
//

#include "MySQLConnectionPool.h"

std::shared_ptr<sql::Connection> MySQLConnectionPool::createConnection() {
    // 获取MySQL驱动实例并创建连接
    sql::mysql::MySQL_Driver *driver;
    sql::Connection *conn;

    driver = sql::mysql::get_driver_instance();
    conn = driver->connect(MySQLAddress, MySQLAccount, MySQLPassword);

    if (conn) {
        // 自定义删除器，用于在连接释放时候关闭连接
        return std::shared_ptr<sql::Connection>(conn, [this](sql::Connection *conn) {
            try {
                conn->close();
            }
            catch (const std::exception &e) {
                std::cerr << "Failed to close connection: " << e.what() << std::endl;
            }
            delete conn;
        });
    }

    return nullptr;
}

MySQLConnectionPool::MySQLConnectionPool() {
    for (int i = 0; i < maxPoolSize; i++) {
        std::shared_ptr<sql::Connection> conn(createConnection());
        if (conn) {
            pool_.push(conn);
        }
    }
}

MySQLConnectionPool::~MySQLConnectionPool() {
    std::lock_guard<std::mutex> lock(mutex_);
    while (!pool_.empty()) {
        std::shared_ptr<sql::Connection> conn = pool_.front();
        pool_.pop();
        if (conn) {
            conn->close();
        }
    }
}


std::shared_ptr<sql::Connection> MySQLConnectionPool::getConnection() {
    std::unique_lock<std::mutex> lock(mutex_);

    // 如果连接池为空，则等待有可用连接或超时
    while (pool_.empty()) {
        if (cv_.wait_for(lock, std::chrono::seconds(5)) == std::cv_status::timeout) {
            // 如果等待超时，则创建一个新的连接
            std::cerr << "Connection timeout. Creating a new connection.\n";
            return createConnection();
        }
    }

    // 从连接池中获取一个连接
    std::shared_ptr<sql::Connection> conn = pool_.front();
    pool_.pop();

    // 验证连接是否仍然有效
    try {
        if (conn->isClosed() || !conn->isValid()) {
            std::cerr << "Invalid connection. Creating a new connection.\n";
            // 关闭连接避免内存泄漏
            conn->close();
            return createConnection();
        }
    }
    catch (const sql::SQLException &e) {
        std::cerr << "Error while validating connection: " << e.what() << std::endl;
        // 关闭连接避免内存泄漏
        conn->close();
        return createConnection();
    }

    return conn;
}

void MySQLConnectionPool::releaseConnection(std::shared_ptr<sql::Connection> conn) {
    std::lock_guard<std::mutex> lock(mutex_);

    // 将连接释放会连接池
    pool_.push(conn);

    // 通知等待的线程有新的连接可用
    cv_.notify_one();
}